// eslint-disable-next-line n/no-extraneous-import
import colormap from 'colormap';

// 处理结果接口
export interface ProcessedData {
  fftImage: ImageBitmap;
  maxFftImage: ImageBitmap;
  waterfallImage: ImageBitmap;
}

/**
 * 频率范围
 */
interface FreqRange {
  left: number;
  right: number;
}

/**
 * 电平范围
 */
interface LevelRange {
  bottom: number;
  top: number;
}

export type WorkerMessage =
  | { payload: FreqRange; type: 'setShowFreqRange' }
  | { payload: LevelRange; type: 'fftLevelRange' }
  | { payload: ProcessedData; type: 'processedData' }
  | { payload: { bottom: number; top: number }; type: 'setShowLevelRange' }
  | { payload: { computeMaxFft: boolean }; type: 'setComputeMaxFft' }
  | {
      payload: { data: number[]; startFreq: number; stopFreq: number };
      type: 'setFftData';
    }
  | {
      payload: { image: ImageBitmap; scheme: string; steps: number };
      type: 'colorLegend';
    }
  | { payload: { scheme: string; steps?: number }; type: 'setColorMap' };

// 任务队列接口
interface ProcessTask {
  fftData: number[];
  fftFreqRange: FreqRange;
  id: number;
  timestamp: number;
}

// interface DrawPoint {
//   x: number;
//   y: number;
// }

// 初始化时或数据范围变化时预计算
let freqScale: number;
let levelScale: number;
let freqOffset: number;
let levelOffset: number;

let computeMaxFft = false; // 是否计算最大值FFT
let maxFftData: number[] = []; // 最大频谱点
let maxFftFreqRange: FreqRange = { left: 0, right: 100 };

const FFT_RECT_MAX_WIDTH = 3000; // 最大瀑布图宽度
const FFT_RECT_MAX_HEIGHT = 300; // 最大历史数据长度

const MAX_WATERFALL_WIDTH = 2048; // 最大瀑布图宽度
const MAX_HISTORY_LENGTH = 100; // 最大历史数据长度

const ctx: Worker = globalThis as unknown as Worker; // 类型断言，避免 DedicatedWorkerGlobalScope 未定义
// let lastTask: null | ProcessTask = null; // 上一次任务（未使用，移除）
const taskQueue: ProcessTask[] = []; // 任务队列
let isProcessing = false; // 是否正在处理任务
let taskIdCounter = 0; // 任务ID计数器

// 频谱图相关
let fftCanvas: OffscreenCanvas = new OffscreenCanvas(
  FFT_RECT_MAX_WIDTH,
  FFT_RECT_MAX_HEIGHT,
); // 离屏画布
let fftCanvasCtx: null | OffscreenCanvasRenderingContext2D =
  fftCanvas.getContext('2d', { willReadFrequently: true }); // 离屏画布上下文

// 最大值FFT相关
let maxFftCanvas: OffscreenCanvas = new OffscreenCanvas(
  FFT_RECT_MAX_WIDTH,
  FFT_RECT_MAX_HEIGHT,
); // 离屏画布
let maxFftCanvasCtx: null | OffscreenCanvasRenderingContext2D =
  maxFftCanvas.getContext('2d', { willReadFrequently: true }); // 离屏画布上下文

// 瀑布图相关
let waterfallCanvas: OffscreenCanvas = new OffscreenCanvas(
  MAX_WATERFALL_WIDTH,
  MAX_HISTORY_LENGTH,
); // 离屏画布
let waterfallCanvasCtx: null | OffscreenCanvasRenderingContext2D =
  waterfallCanvas.getContext('2d', { willReadFrequently: true }); // 离屏画布上下文
let waterfallImageData: ImageData = waterfallCanvasCtx?.createImageData(
  MAX_WATERFALL_WIDTH,
  MAX_HISTORY_LENGTH,
) as ImageData; // 瀑布图绘制的图片数据
let waterfallBackImageData: ImageData = waterfallCanvasCtx?.createImageData(
  MAX_WATERFALL_WIDTH,
  MAX_HISTORY_LENGTH,
) as ImageData; // 备份瀑布图数据

let showFreqRange: FreqRange = { left: 0, right: 3000 };
let showLevelRange: LevelRange = { top: 500, bottom: -500 };

let colorScheme: { b: number; g: number; r: number }[] = [];
const DEFAULT_COLOR_STEPS = 256;

// 初始化默认颜色映射
(async () => {
  await updateColorMap('jet', DEFAULT_COLOR_STEPS);
})();

// 生成渐变色图例
async function generateColorLegend(): Promise<ImageBitmap> {
  const legendWidth = 20;
  const legendHeight = 256;

  const legendCanvas = new OffscreenCanvas(legendWidth, legendHeight);
  const legendCtx = legendCanvas.getContext('2d');

  if (!legendCtx) throw new Error('Legend canvas init failed');

  const imageData = legendCtx.createImageData(legendWidth, legendHeight);

  // 从上到下绘制渐变色条
  for (let y = 0; y < legendHeight; y++) {
    const normalizedValue = 1 - y / (legendHeight - 1); // 从上到下：1到0
    const colorIndex = Math.floor(normalizedValue * (colorScheme.length - 1));
    const color = colorScheme[colorIndex] || { r: 0, g: 0, b: 0 };

    // 填充整行
    for (let x = 0; x < legendWidth; x++) {
      const pixelIndex = (y * legendWidth + x) * 4;
      imageData.data[pixelIndex] = color.r; // R
      imageData.data[pixelIndex + 1] = color.g; // G
      imageData.data[pixelIndex + 2] = color.b; // B
      imageData.data[pixelIndex + 3] = 255; // A
    }
  }

  legendCtx.putImageData(imageData, 0, 0);
  return legendCanvas.transferToImageBitmap();
}

// 更新颜色映射
async function updateColorMap(scheme: string, steps = DEFAULT_COLOR_STEPS) {
  colorScheme = colormap({
    colormap: scheme,
    nshades: steps,
    format: 'rgba',
    alpha: 1,
  }).map((c: any[]) => ({
    r: c[0],
    g: c[1],
    b: c[2],
  }));

  // 生成并发送渐变色图例
  try {
    const legendImage = await generateColorLegend();
    ctx.postMessage({
      type: 'colorLegend',
      payload: {
        image: legendImage,
        scheme,
        steps,
      },
    });
  } catch (error) {
    console.error('生成渐变色图例失败:', error);
  }
}

// 获取归一化颜色
const getColor = (level: number) => {
  if (level === showLevelRange.bottom) level = showLevelRange.bottom + 1;
  const normalized = Math.min(
    1,
    Math.max(
      0,
      (level - showLevelRange.bottom) /
        (showLevelRange.top - showLevelRange.bottom),
    ),
  );

  const index = Math.floor(normalized * (colorScheme.length - 1));
  if (index < 0 || index >= colorScheme.length) {
    return { r: 0, g: 0, b: 0 };
  }
  return colorScheme[index] || { r: 0, g: 0, b: 0 };
};

// 计算最大值FFT电平范围
const computeFftLevelRange = (fftData: number[]) => {
  if (fftData.length === 0) {
    return { top: 0, bottom: 0 };
  }

  let minLevel = fftData[0] as number;
  let maxLevel = fftData[0] as number;

  // 使用循环而不是扩展运算符，避免调用栈溢出
  for (const value of fftData) {
    if (value < minLevel) minLevel = value;
    if (value > maxLevel) maxLevel = value;
  }

  return {
    top: maxLevel,
    bottom: minLevel,
  };
};

// 添加任务到队列
const enqueueTask = (task: Omit<ProcessTask, 'id' | 'timestamp'>) => {
  const newTask = {
    ...task,
    id: taskIdCounter++,
    timestamp: performance.now(),
  };

  // 队列容量控制（保留最新20条）
  if (taskQueue.length > 20) {
    const discarded = taskQueue.shift();
    if (discarded) {
      console.warn(`队列溢出，丢弃任务#${discarded.id}`);
    } else {
      console.warn('队列溢出，丢弃任务但未找到任务');
    }
  }

  taskQueue.push(newTask);

  if (!isProcessing) {
    processQueue();
  }
};

// 队列处理核心逻辑
const processQueue = async () => {
  if (taskQueue.length === 0) {
    isProcessing = false;
    return;
  }

  isProcessing = true;
  const task = taskQueue.shift();
  if (!task) {
    isProcessing = false;
    return;
  }
  // lastTask = task;
  if (!task.fftData) {
    isProcessing = false;
    return;
  }
  try {
    const maxLevelRange = computeFftLevelRange(task.fftData);
    ctx.postMessage({
      type: 'fftLevelRange',
      payload: maxLevelRange,
    });

    const fftImage = await generateFftImage(task);
    let maxFftImage: ImageBitmap | undefined;
    if (computeMaxFft) {
      maxFftImage = await generateMaxFftImage(task);
    }
    // 生成瀑布图位图
    const waterfallImage = await generateWaterfallImage(task);

    ctx.postMessage({
      type: 'processedData',
      payload: { fftImage, maxFftImage, waterfallImage },
    });
  } catch (error) {
    console.error(`处理任务#${task.id}失败:`, error);
  }

  // 继续处理下一个任务
  processQueue();
};

function updateScales() {
  // 频率计算参数
  const freqRange = showFreqRange.right - showFreqRange.left;
  freqScale = FFT_RECT_MAX_WIDTH / freqRange; // 避免每次计算除法
  freqOffset = -showFreqRange.left * freqScale;

  // 电平计算参数
  const levelRange = showLevelRange.top - showLevelRange.bottom;
  levelScale = FFT_RECT_MAX_HEIGHT / levelRange; // 电平缩放比例
  levelOffset = showLevelRange.top * levelScale; // 电平偏移量
}

updateScales();

// 生成频谱图位图
const generateFftImage = async (task: ProcessTask) => {
  const { fftData, fftFreqRange } = task;

  if (!fftCanvasCtx) throw new Error('Canvas init failed');
  if (!fftCanvas) {
    // 重建画布
    fftCanvas = new OffscreenCanvas(FFT_RECT_MAX_WIDTH, FFT_RECT_MAX_HEIGHT);
    fftCanvasCtx = fftCanvas.getContext('2d', { willReadFrequently: true }); // 离屏画布上下文
  }

  // 生成频谱点 - 不使用Math.round()以保持精度
  const freqStep = (fftFreqRange.right - fftFreqRange.left) / fftData.length;
  const fftPoints = fftData.map((level, index) => ({
    x: (freqStep * index + fftFreqRange.left) * freqScale + freqOffset,
    y: levelOffset - level * levelScale,
  }));

  // 绘制频谱图
  const painter = fftCanvasCtx;
  if (!painter) throw new Error('Painter init failed');

  // 清除画布
  painter.clearRect(0, 0, fftCanvas.width, fftCanvas.height);

  painter.save();
  painter.strokeStyle = '#d7f752';
  painter.lineWidth = 2; // 增加线宽以改善缩放显示效果
  painter.lineCap = 'round'; // 圆润的线端
  painter.lineJoin = 'round'; // 圆润的连接点
  painter.beginPath();

  // 绘制连续的线条
  if (
    fftPoints.length > 0 &&
    fftPoints[0] &&
    typeof fftPoints[0].x === 'number' &&
    typeof fftPoints[0].y === 'number'
  ) {
    painter.moveTo(fftPoints[0].x, fftPoints[0].y);
  }

  for (const point of fftPoints) {
    if (Number.isNaN(point.x) || Number.isNaN(point.y)) {
      console.warn('Skipping NaN point:', point);
      continue;
    }
    painter.lineTo(point.x, point.y);
  }
  painter.stroke();
  painter.restore();
  // 将画布上的图片保存到图片
  return fftCanvas.transferToImageBitmap();
};

// 生成最大值频谱图位图
const generateMaxFftImage = async (task: ProcessTask) => {
  const { fftData, fftFreqRange } = task;

  if (!maxFftCanvasCtx) throw new Error('Canvas init failed');
  if (!maxFftCanvas) {
    // 重建画布
    maxFftCanvas = new OffscreenCanvas(FFT_RECT_MAX_WIDTH, FFT_RECT_MAX_HEIGHT);
    maxFftCanvasCtx = maxFftCanvas.getContext('2d', {
      willReadFrequently: true,
    }); // 离屏画布上下文
  }

  if (
    maxFftData.length !== fftData.length ||
    maxFftFreqRange.left !== fftFreqRange.left ||
    maxFftFreqRange.right !== fftFreqRange.right
  ) {
    maxFftData = fftData;
    maxFftFreqRange = fftFreqRange;
  } else {
    for (const [i, fftDatum] of fftData.entries()) {
      if (
        Array.isArray(maxFftData) &&
        maxFftData[i] !== undefined &&
        fftDatum > maxFftData[i]
      ) {
        maxFftData[i] = fftDatum;
      }
    }
  }

  const freqStep = (fftFreqRange.right - fftFreqRange.left) / fftData.length;

  const fftPoints = maxFftData.map((level, index) => ({
    x: Math.round(
      (freqStep * index + fftFreqRange.left) * freqScale + freqOffset,
    ),
    y: Math.round(levelOffset - level * levelScale),
  }));

  const painter = maxFftCanvasCtx;
  if (!painter) throw new Error('Painter init failed');
  // 清除画布
  painter.clearRect(0, 0, fftCanvas.width, fftCanvas.height);

  painter.save();
  painter.strokeStyle = '#709e07';
  painter.lineWidth = 2;
  painter.lineCap = 'round'; // 圆润的线端
  painter.lineJoin = 'round'; // 圆润的连接点
  painter.beginPath();
  if (
    fftPoints.length > 0 &&
    fftPoints[0] &&
    typeof fftPoints[0].x === 'number' &&
    typeof fftPoints[0].y === 'number'
  ) {
    painter.moveTo(fftPoints[0].x, fftPoints[0].y);
    for (let i = 1; i < fftPoints.length; i++) {
      if (
        fftPoints[i]?.x !== undefined &&
        typeof fftPoints[i]?.x === 'number' &&
        fftPoints[i]?.y !== undefined &&
        typeof fftPoints[i]?.y === 'number'
      ) {
        painter.lineTo(fftPoints[i]?.x ?? 0, fftPoints[i]?.y ?? 0);
      }
    }
  }
  painter.stroke();
  painter.restore();
  // 将画布上的图片保存到图片
  return maxFftCanvas.transferToImageBitmap();
};

// 生成瀑布图位图
const generateWaterfallImage = async (task: ProcessTask) => {
  const { fftData, fftFreqRange } = task;
  // const start = performance.now();
  if (!waterfallCanvasCtx) throw new Error('Canvas init failed');
  if (!waterfallCanvas) {
    // 重建画布
    waterfallCanvas = new OffscreenCanvas(
      MAX_WATERFALL_WIDTH,
      MAX_HISTORY_LENGTH,
    );
    waterfallCanvasCtx = waterfallCanvas.getContext('2d', {
      willReadFrequently: true,
    }); // 离屏画布上下文

    waterfallImageData = waterfallCanvasCtx?.createImageData(
      MAX_WATERFALL_WIDTH,
      MAX_HISTORY_LENGTH,
    ) as ImageData;
    waterfallBackImageData = waterfallCanvasCtx?.createImageData(
      MAX_WATERFALL_WIDTH,
      MAX_HISTORY_LENGTH,
    ) as ImageData;
  }

  // 将旧数据复制到新数据的第二行及之后
  const startOffset = MAX_WATERFALL_WIDTH * 4; // 每行占 4*targetWidth 字节
  waterfallImageData.data.set(
    waterfallBackImageData.data.slice(
      0,
      waterfallBackImageData.data.length - startOffset,
    ),
    startOffset,
  );

  const showFreqWidth = showFreqRange.right - showFreqRange.left;
  const fftFreqWidth = fftFreqRange.right - fftFreqRange.left;

  let startPx = 0;
  let endPx = MAX_WATERFALL_WIDTH;

  startPx =
    fftFreqRange.left <= showFreqRange.left
      ? 0
      : Math.floor(
          ((fftFreqRange.left - showFreqRange.left) / showFreqWidth) *
            MAX_WATERFALL_WIDTH,
        );

  endPx =
    fftFreqRange.right >= showFreqRange.right
      ? MAX_WATERFALL_WIDTH
      : Math.floor(
          ((fftFreqRange.right - showFreqRange.left) / showFreqWidth) *
            MAX_WATERFALL_WIDTH,
        );

  const freqStep = showFreqWidth / (endPx - startPx); // 绘制宽度的分辨率

  for (let i = startPx; i < endPx; i++) {
    const pxFreq = i * freqStep + showFreqRange.left;
    if (pxFreq < fftFreqRange.left || pxFreq > fftFreqRange.right) {
      // console.log(`pxFreq: ${pxFreq} 超出范围`);
      continue;
    }
    let dataIndex = Math.floor(
      ((pxFreq - fftFreqRange.left) / fftFreqWidth) * fftData.length,
    );
    dataIndex = Math.min(fftData.length - 1, dataIndex);
    const level = fftData[dataIndex];
    const color = getColor(level as number);
    const idx = i * 4; // y=0行
    waterfallImageData.data.set([color.r, color.g, color.b, 255], idx);
  }
  // 备份当前数据
  waterfallBackImageData.data.set(waterfallImageData.data, 0);
  // const end = performance.now();
  // console.log(`生成瀑布图时间: ${end - start} ms`);

  waterfallCanvasCtx?.putImageData(
    waterfallImageData,
    0,
    0,
    0,
    0,
    MAX_WATERFALL_WIDTH,
    MAX_HISTORY_LENGTH,
  );
  return waterfallCanvas.transferToImageBitmap();
};

ctx.addEventListener('message', async (e: MessageEvent<WorkerMessage>) => {
  switch (e.data.type) {
    case 'setColorMap': {
      (async () => {
        const payload = e.data.payload as { scheme: string; steps?: number };
        await updateColorMap(payload.scheme, payload.steps);
      })();
      break;
    }

    case 'setComputeMaxFft': {
      computeMaxFft = e.data.payload.computeMaxFft;
      if (!computeMaxFft) {
        maxFftData = [];
      }
      break;
    }

    case 'setFftData': {
      enqueueTask({
        fftData: e.data.payload.data,
        fftFreqRange: {
          left: e.data.payload.startFreq,
          right: e.data.payload.stopFreq,
        },
      });
      break;
    }

    case 'setShowFreqRange': {
      if (e.data.payload !== showFreqRange) {
        // console.log(`更新频率范围: ${showFreqRange}`);
        showFreqRange = e.data.payload;
        updateScales();
      }
      break;
    }

    case 'setShowLevelRange': {
      if (e.data.payload !== showLevelRange) {
        // console.log(`更新电平范围: ${showLevelRange}`);
        showLevelRange = e.data.payload;
        updateScales();
      }
      break;
    }
  }
});
